#include "set.h"
#include <iostream>

using namespace setex;

Set* Set::SetUnion(Set* s)
{
    if (s == NULL)
    {
        return NULL;
    }

    doublelist::ListElmt* head = this->m_data.ListHead();
    Set* ret = new Set();
    while (head)
    {
        ret->SetInsert(head->GetData());
        head = head->GetNext();
    }

    head = s->GetData()->ListHead();
    while(head)
    {
        if (!this->IsSetMember(head->GetData()))
        {
            ret->SetInsert(head->GetData());
        }
        head = head->GetNext();
    }

    return ret;
}

Set* Set::SetIntersection(Set* s)
{
    if (s == NULL)
    {
        return NULL;
    }

    Set* ret = new Set();
    doublelist::ListElmt* head = this->m_data.ListHead();
    while (head)
    {
        if (s->IsSetMember(head->GetData()))
        {
            ret->SetInsert(head->GetData());
        }
        head = head->GetNext();
    }

    return ret;
}

Set* Set::SetDifference(Set* s)
{
    if (s == NULL)
    {
        return NULL;
    }

    Set* ret = new Set();
    doublelist::ListElmt* head = this->m_data.ListHead();
    while (head)
    {
        if (!s->IsSetMember(head->GetData()))
        {
            ret->SetInsert(head->GetData());
        }
        head = head->GetNext();
    }

    return ret;
}

void Set::SetInsert(int d)
{
    this->m_data.ListInsert(new doublelist::ListElmt(d));
}

void Set::SetRemove(int d)
{
    doublelist::ListElmt* head = this->m_data.ListHead();
    while(head)
    {
        if (head->GetData() == d)
        {
            this->m_data.ListDel(head);
            return;
        }
        head = head->GetNext();
    }
}

bool Set::IsSetMember(int d)
{
    doublelist::ListElmt* head = this->m_data.ListHead();
    while(head)
    {
        if (head->GetData() == d)
        {
            return true;
        }
        head = head->GetNext();
    }

    return false;
}

bool Set::IsSetEqual(Set* s)
{
    if (s == NULL)
    {
        return false;
    }

    if (this->m_data.GetListSize() != s->GetSetSize())
    {
        return false;
    }

    doublelist::ListElmt* head = this->m_data.ListHead();
    while (head)
    {
        if (!s->IsSetMember(head->GetData()))
        {
            return false;
        }
        head = head->GetNext();
    }

    return true;
}

bool Set::IsSetSubset(Set* s)
{
    if (s == NULL)
    {
        return false;
    }

    doublelist::ListElmt* head = s->GetData()->ListHead();
    while(head)
    {
        if (!this->IsSetMember(head->GetData()))
        {
            return false;
        }
        head = head->GetNext();
    }

    return true;
}

int Set::GetSetSize()
{
    return this->m_data.GetListSize();
}

doublelist::DoubleList* Set::GetData()
{
    return &this->m_data;
}

void setex::PrintSet(Set* s)
{
    std::cout << "cur data: ";
    doublelist::ListElmt* head = s->GetData()->ListHead();
    while (head)
    {
        std::cout << head->GetData() << " ";
        head = head->GetNext();
    }
    std::cout << std::endl;
    std::cout << "set size: " << s->GetSetSize() << std::endl;
}
